clutter_actor_paint (CLUTTER_ACTOR (priv->label));
}
-static void
-st_tooltip_map (ClutterActor *self)
-{
- StTooltipPrivate *priv = ST_TOOLTIP (self)->priv;
-
- CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->map (self);
-
- clutter_actor_map (CLUTTER_ACTOR (priv->label));
-}
-
-static void
-st_tooltip_unmap (ClutterActor *self)
-{
- StTooltipPrivate *priv = ST_TOOLTIP (self)->priv;
-
- CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->unmap (self);
-
- clutter_actor_unmap (CLUTTER_ACTOR (priv->label));
-}
-
static void
st_tooltip_dispose (GObject *self)
{
actor_class->get_preferred_height = st_tooltip_get_preferred_height;
actor_class->allocate = st_tooltip_allocate;
actor_class->paint = st_tooltip_paint;
- actor_class->map = st_tooltip_map;
- actor_class->unmap = st_tooltip_unmap;
actor_class->show = st_tooltip_show;
actor_class->show_all = st_tooltip_show_all;
actor_class->hide_all = st_tooltip_hide_all;
StTooltipPrivate *priv = tooltip->priv;
ClutterGeometry *tip_area = tooltip->priv->tip_area;
gfloat tooltip_w, tooltip_h, tooltip_x, tooltip_y;
- gfloat stage_w, stage_h;
- ClutterActor *stage;
-
- /* ensure the tooltip with is not fixed size */
- clutter_actor_set_size ((ClutterActor*) tooltip, -1, -1);
+ gfloat parent_w, parent_h;
+ ClutterActor *parent;
/* if no area set, just position ourselves top left */
if (!priv->tip_area)
{
- clutter_actor_set_position ((ClutterActor*) tooltip, 0, 0);
+ clutter_actor_set_anchor_point ((ClutterActor*) tooltip, 0, 0);
return;
}
tooltip_x = (int)(tip_area->x + (tip_area->width / 2) - (tooltip_w / 2));
tooltip_y = (int)(tip_area->y + tip_area->height);
- stage = clutter_actor_get_stage ((ClutterActor *) tooltip);
- if (!stage)
+ parent = clutter_actor_get_parent ((ClutterActor *) tooltip);
+ if (!parent)
{
+ g_critical ("StTooltip is not parented");
return;
}
- clutter_actor_get_size (stage, &stage_w, &stage_h);
+ clutter_actor_get_size (parent, &parent_w, &parent_h);
/* make sure the tooltip is not off screen vertically */
- if (tooltip_w > stage_w)
+ if (tooltip_x < 0)
{
tooltip_x = 0;
- clutter_actor_set_width ((ClutterActor*) tooltip, stage_w);
}
- else if (tooltip_x < 0)
+ else if (tooltip_x + tooltip_w > parent_w)
{
- tooltip_x = 0;
- }
- else if (tooltip_x + tooltip_w > stage_w)
- {
- tooltip_x = (int)(stage_w) - tooltip_w;
+ tooltip_x = (int)(parent_w) - tooltip_w;
}
/* make sure the tooltip is not off screen horizontally */
- if (tooltip_y + tooltip_h > stage_h)
+ if (tooltip_y + tooltip_h > parent_h)
{
priv->actor_below = TRUE;
-
- /* re-query size as may have changed */
- clutter_actor_get_preferred_height ((ClutterActor*) tooltip,
- -1, NULL, &tooltip_h);
tooltip_y = tip_area->y - tooltip_h;
}
else
/* calculate the arrow offset */
priv->arrow_offset = tip_area->x + tip_area->width / 2 - tooltip_x;
- clutter_actor_set_position ((ClutterActor*) tooltip, tooltip_x, tooltip_y);
+ /* Since we are updating the position out of st_widget_allocate(), we can't
+ * call clutter_actor_set_position(), since that would trigger another
+ * allocation cycle. Instead, we adjust the anchor position which moves
+ * the tooltip actor on the screen without changing its allocation
+ */
+ clutter_actor_set_anchor_point ((ClutterActor*) tooltip, -tooltip_x, -tooltip_y);
}
/**
st_tooltip_show (ClutterActor *self)
{
StTooltip *tooltip = ST_TOOLTIP (self);
- ClutterActor *parent;
- ClutterActor *stage;
-
- parent = clutter_actor_get_parent (self);
- stage = clutter_actor_get_stage (self);
-
- if (!stage)
- {
- g_warning ("StTooltip is not on any stage.");
- return;
- }
-
- /* make sure we're parented on the stage */
- if (G_UNLIKELY (parent != stage))
- {
- g_object_ref (self);
- clutter_actor_unparent (self);
- clutter_actor_set_parent (self, stage);
- g_object_unref (self);
- parent = stage;
- }
-
- /* raise the tooltip to the top */
- clutter_container_raise_child (CLUTTER_CONTAINER (stage),
- CLUTTER_ACTOR (tooltip),
- NULL);
st_tooltip_update_position (tooltip);
g_boxed_free (CLUTTER_TYPE_GEOMETRY, tooltip->priv->tip_area);
tooltip->priv->tip_area = g_boxed_copy (CLUTTER_TYPE_GEOMETRY, area);
- st_tooltip_update_position (tooltip);
+ if (clutter_actor_get_stage (CLUTTER_ACTOR (tooltip)))
+ st_tooltip_update_position (tooltip);
}
/**
gboolean is_stylable : 1;
gboolean has_tooltip : 1;
+ gboolean show_tooltip : 1;
gboolean is_style_dirty : 1;
gboolean draw_bg_color : 1;
gboolean draw_border_internal : 1;
static AtkObject * st_widget_get_accessible (ClutterActor *actor);
+static void st_widget_do_show_tooltip (StWidget *widget);
+static void st_widget_do_hide_tooltip (StWidget *widget);
+
static void
st_widget_set_property (GObject *gobject,
guint prop_id,
if (priv->tooltip)
{
- ClutterContainer *parent;
- ClutterActor *tooltip = CLUTTER_ACTOR (priv->tooltip);
-
- /* this is just a little bit awkward because the tooltip is parented
- * on the stage, but we still want to "own" it */
- parent = CLUTTER_CONTAINER (clutter_actor_get_parent (tooltip));
-
- if (parent)
- clutter_container_remove_actor (parent, tooltip);
-
+ clutter_actor_destroy (CLUTTER_ACTOR (priv->tooltip));
+ g_object_unref (priv->tooltip);
priv->tooltip = NULL;
}
static void
st_widget_map (ClutterActor *actor)
{
- StWidgetPrivate *priv = ST_WIDGET (actor)->priv;
+ StWidget *self = ST_WIDGET (actor);
CLUTTER_ACTOR_CLASS (st_widget_parent_class)->map (actor);
- st_widget_ensure_style ((StWidget*) actor);
+ st_widget_ensure_style (self);
- if (priv->tooltip)
- clutter_actor_map ((ClutterActor *) priv->tooltip);
+ if (self->priv->show_tooltip)
+ st_widget_do_show_tooltip (self);
}
static void
st_widget_unmap (ClutterActor *actor)
{
- StWidgetPrivate *priv = ST_WIDGET (actor)->priv;
+ StWidget *self = ST_WIDGET (actor);
+ StWidgetPrivate *priv = self->priv;
CLUTTER_ACTOR_CLASS (st_widget_parent_class)->unmap (actor);
- if (priv->tooltip)
- clutter_actor_unmap ((ClutterActor *) priv->tooltip);
-
if (priv->track_hover && priv->hover)
- st_widget_set_hover (ST_WIDGET (actor), FALSE);
+ st_widget_set_hover (self, FALSE);
+
+ st_widget_do_hide_tooltip (self);
}
static void notify_children_of_style_change (ClutterContainer *container);
st_widget_style_changed (self);
}
+static void
+st_widget_ensure_tooltip_parented (StWidget *widget, ClutterStage *stage)
+{
+ StWidgetPrivate *priv;
+ ClutterContainer *ui_root;
+ ClutterActor *tooltip, *parent;
+
+ priv = widget->priv;
+
+ ui_root = st_get_ui_root (stage);
+
+ tooltip = CLUTTER_ACTOR (priv->tooltip);
+ parent = clutter_actor_get_parent (tooltip);
+
+ if (G_UNLIKELY (parent != CLUTTER_ACTOR (ui_root)))
+ {
+ if (parent)
+ clutter_container_remove_actor (CLUTTER_CONTAINER (parent), tooltip);
+
+ clutter_container_add_actor (ui_root, tooltip);
+ }
+}
+
/**
* st_widget_set_has_tooltip:
* @widget: A #StWidget
gboolean has_tooltip)
{
StWidgetPrivate *priv;
+ ClutterActor *stage;
g_return_if_fail (ST_IS_WIDGET (widget));
if (!priv->tooltip)
{
priv->tooltip = g_object_new (ST_TYPE_TOOLTIP, NULL);
- clutter_actor_set_parent ((ClutterActor *) priv->tooltip,
- (ClutterActor *) widget);
+ g_object_ref_sink (priv->tooltip);
+
+ stage = clutter_actor_get_stage (CLUTTER_ACTOR (widget));
+ if (stage != NULL)
+ st_widget_ensure_tooltip_parented (widget, CLUTTER_STAGE (stage));
}
}
- else
+ else if (priv->tooltip)
{
- if (priv->tooltip)
- {
- clutter_actor_unparent (CLUTTER_ACTOR (priv->tooltip));
- priv->tooltip = NULL;
- }
+ clutter_actor_destroy (CLUTTER_ACTOR (priv->tooltip));
+ g_object_unref (priv->tooltip);
+ priv->tooltip = NULL;
}
}
if (text == NULL)
st_widget_set_has_tooltip (widget, FALSE);
else
- st_widget_set_has_tooltip (widget, TRUE);
-
- st_tooltip_set_label (priv->tooltip, text);
+ {
+ st_widget_set_has_tooltip (widget, TRUE);
+ st_tooltip_set_label (priv->tooltip, text);
+ }
}
/**
* st_widget_show_tooltip:
* @widget: A #StWidget
*
- * Show the tooltip for @widget
+ * Force the tooltip for @widget to be shown
*
*/
void
st_widget_show_tooltip (StWidget *widget)
{
- gfloat x, y, width, height;
- ClutterGeometry area;
-
g_return_if_fail (ST_IS_WIDGET (widget));
- /* XXX not necceary, but first allocate transform is wrong */
-
- clutter_actor_get_transformed_position ((ClutterActor*) widget,
- &x, &y);
-
- clutter_actor_get_size ((ClutterActor*) widget, &width, &height);
+ widget->priv->show_tooltip = TRUE;
+ if (CLUTTER_ACTOR_IS_MAPPED (widget))
+ st_widget_do_show_tooltip (widget);
+}
- area.x = x;
- area.y = y;
- area.width = width;
- area.height = height;
+static void
+st_widget_do_show_tooltip (StWidget *widget)
+{
+ ClutterActor *stage, *tooltip;
+ stage = clutter_actor_get_stage (CLUTTER_ACTOR (widget));
+ g_return_if_fail (stage != NULL);
if (widget->priv->tooltip)
{
- st_tooltip_set_tip_area (widget->priv->tooltip, &area);
- clutter_actor_show_all (CLUTTER_ACTOR (widget->priv->tooltip));
+ tooltip = CLUTTER_ACTOR (widget->priv->tooltip);
+ st_widget_ensure_tooltip_parented (widget, CLUTTER_STAGE (stage));
+ clutter_actor_raise (tooltip, NULL);
+ clutter_actor_show_all (tooltip);
}
}
{
g_return_if_fail (ST_IS_WIDGET (widget));
+ widget->priv->show_tooltip = FALSE;
+ if (CLUTTER_ACTOR_IS_MAPPED (widget))
+ st_widget_do_hide_tooltip (widget);
+}
+
+static void
+st_widget_do_hide_tooltip (StWidget *widget)
+{
if (widget->priv->tooltip)
clutter_actor_hide (CLUTTER_ACTOR (widget->priv->tooltip));
}